import 'reflect-metadata'
// 参数装饰器
// 参数装饰器声明在一个参数声明之前（紧靠着参数声明）。 参数装饰器应用于类构造函数或方法声明。 参数装饰器不能用在声明文件（.d.ts），重载或其它任何修饰符不能应用的场景。 参数装饰器应用于类构造函数或方法声明。 参数装饰器表达式会在运行时当作函数被调用，传入下列3个参数：
// target: 对于静态成员来说是类的构造函数，对于实例成员是类的原型对象。
// key: 成员的名字。
// index: 参数在函数参数列表中的索引。

// 用于装饰类的构造函数或方法的参数
// 用来是现在方法调用时验证参数的值

const REQURIED_PARAMETERS = 'REQURIED_PARAMETERS'


function validate(target: any, propertyKey: string, parameterIndex: number) {
  const exsitingRequriedParameters = Reflect.getOwnMetadata(REQURIED_PARAMETERS, target, propertyKey) || []
  exsitingRequriedParameters.push(parameterIndex)
  Reflect.defineMetadata(REQURIED_PARAMETERS, exsitingRequriedParameters, target, propertyKey)
}

function validateParameters(target: any, propertyKey: string, descriptor: PredefinedColorSpace) {
  // @ts-ignore
  const originalMethod = descriptor.value
  // @ts-ignore
  descriptor.value = function (...args: any[]) {
    const exsitingRequriedParameters = Reflect.getOwnMetadata(REQURIED_PARAMETERS, target, propertyKey) || []
    for (let index of exsitingRequriedParameters) {
      if (args[index] === undefined) {
        throw new Error(`参数${index}不能为空`)
      }
    }
    return originalMethod.apply(this, args)
  }
}

class User {
  constructor(private name: string, private age: number) {}
  // @ts-ignore
  @validateParameters
  setName(name: string, @validate age: number) {
    this.name = name
    this.age = age
  }
}

const user = new User('张三', 10)
// user.setName('李四', 20)
user.setName(undefined, undefined)



